<template>
  <div class="qr-code lx-qr-code" :class="{ error: error }" v-loading="loading" :style="{width:`${width + 20}px`,height:`${height + 30}px`,padding:`${padding}px`}">
    <div class="qr-error login-tips" v-if="!hasLogin">
      <el-button size="small" type="primary" @click="$emit('login')">请先登录</el-button>
    </div>
    <div class="code-box"
      v-show="hasLogin">
      <div
        ref="qrCode"
        key="code">
      </div>
    </div>
    <div v-if="hasLogin && error"
      class="refresh qr-error"
      key="refresh"
      @click="refreshCode">
        <svg-icon icon-class="code-refresh" />
        <p class="text-error">{{error}}</p>
    </div>
  </div>
</template>
<script lang="ts">
// @ts-ignore
import QRCode from 'qrcodejs2-fix'
// @ts-ignore
import { createOrderApi, getOrderInfoApi, checkOrderInfo } from './api'
import { debounce } from '@/utils'
import { invokeAsyncAPi, registerInformApi } from '@/xz-fn'
import { systemAppStore } from "@/stores/system";
import { userAppStore } from '@/stores/user';

interface CreateOrderApiType {
  product_id: any[];
  pay_way: number;
  pay_entry: string;
  channel_id: any;
  coupon_id?: any;
  act_id?: any;
}

export default {
  name: 'LxPaymentCode',
  props: {
    hasLogin: {
      type: Boolean,
      default: false
    },
    product: {
      type: Object,
      require: true
    },
    otherParamsStr: {
      type: String,
      default: '{}'
    },
    width: {
      type: Number,
      default: 150
    },
    height: {
      type: Number,
      default: 150
    },
    padding: {
      type: Number,
      default: 10
    },
    openPos: {
      type: String,
      default: 'XZDesktopUserCenter'
    }
  },
  emits: ['refresh', 'onStatusChange', 'login'],
  data () {
    return {
      isOnShow: true,
      loading: false,
      qrcode: null,
      timer: null,
      error: '',
      isAgree: true,
      oldId: '',
      orderInfo: {},
      otherParamsStrCache: ''
    }
  },
  watch: {
    'product.id': {
      handler () {
        if (this.createOrder_) {
          this.createOrder_()
        } else {
          this.createOrder()
        }
      },
      immediate: true
    },
    otherParamsStr () {
      if (this.createOrder_) {
        this.createOrder_()
      } else {
        this.createOrder()
      }
    },
    'hasLogin' () {
      this.createOrder_()
    }
  },
  mounted () {
    const container = this.$refs.qrCode
    this.qrcode = new QRCode(container, {
      text: this.text,
      width: this.width - this.padding * 2,
      height: this.height - this.padding * 2,
      colorDark: '#000000',
      colorLight: '#ffffff',
      correctLevel: 0
    })
  },
  activated () {
    this.isOnShow = true
    this.createOrder()
  },
  deactivated () {
    this.isOnShow = false
    this.createOrder()
  },
  beforeUnmount () {
    this.isOnShow = false
    this.createOrder()
  },
  async created () {
    this.createOrder_ = debounce(() => {
      this.createOrder()
    }, 250, false)

    // 获取联想的支付结果
    registerInformApi('xz_lx_pay_res', (res: any) => {
      console.log('联想支付结果：', res)
      if (res) {
        this.dealPayRes(JSON.parse(res).data)
      } else {
        this.setCodeError()
      }
    })
  },
  methods: {
    refreshCode () {
      this.$emit('refresh')
      this.clearOrder()
      this.createOrder()
    },
    setTime (oldCode: any) {
      clearTimeout(this.timer)

      this.timer = setTimeout(() => {
        if (this.error || oldCode !== this.product.orderid) {
          return
        }

        oldCode = this.product.orderid
        checkOrderInfo({
          orderid: this.product.orderid,
          sign: this.product.sign,
          type: 'lenovo'
        }).then((res: any) => {
          if (oldCode !== this.product.orderid) {
            return
          }

          const data = res.data || {}
          if (data.status === 0) {
            this.emitOrderStatus('succes')
          } else if (data.status === 2) {
            this.error = '订单无效！'
            this.emitOrderStatus('error')
          }
          this.setTime(oldCode)
        }).catch(() => {
          this.setTime(oldCode)
        })
      }, 3000)
    },
    async createOrder () {
      clearTimeout(this.timer)
      if ([!this.isOnShow, !this.hasLogin, !this.isAgree, !this.product.id].includes(true)) return

      const params: CreateOrderApiType = {
        product_id: [this.product.id],
        pay_way: 5, // 联想
        pay_entry: 'web',
        channel_id: systemAppStore().appInfo.channel
      }

      const otherParamsStr = this.otherParamsStr
      this.otherParamsStrCache = otherParamsStr
      const otherParams = JSON.parse(otherParamsStr)

      if (otherParams.couponid) {
        params.coupon_id = otherParams.couponid
      }
      if (otherParams.actid) {
        params.act_id = otherParams.actid
      }

      this.loading = true
      createOrderApi(params).then((res: any) => {
        this.oldId = params.product_id[0] || this.product.id
        if (this.product.id !== this.oldId) {
          this.loading = false
          return
        }
        this.orderInfo = res.data
        this.getOrderInfo()
      }).catch(() => {
        this.setCodeError()
      })
    },
    dealPayRes (res: any) {
      this.loading = false
      if (this.product.id !== this.oldId) {
        return
      }

      this.error = ''
      // eslint-disable-next-line vue/no-mutating-props
      this.product.payURL = res?.tradeUrl
      // eslint-disable-next-line vue/no-mutating-props
      this.product.orderid = this.orderInfo.order_id
      // eslint-disable-next-line vue/no-mutating-props
      this.product.sign = this.orderInfo.sign
      // eslint-disable-next-line vue/no-mutating-props
      this.product.otherParamsStr = this.otherParamsStrCache
      this.makePayCode()
    },
    getOrderInfo () {
      if (!this.orderInfo.order_id) {
        this.setCodeError()
        return
      }

      const orderInfo = {
        type: this.orderInfo.pay_way_str,
        orderid: this.orderInfo.order_id,
        sign: this.orderInfo.sign,
        title: this.orderInfo.title,
        appID: import.meta.env.VITE_APP_MERCHANTID,
        trade_method: 'APP',
        payAppId: (userAppStore().payConfig as any).appid || import.meta.env.VITE_APP_LX_PAY_APP_ID,
        deviceId: userAppStore().lenovoToken ? '' : systemAppStore().appInfo.uuid
      }
      // 调起订单支付
      getOrderInfoApi(orderInfo).then(async (res: any) => {
        // 联想支付
        const params = JSON.parse(res.data.prepayInfo.param)
        params.productCode = 'COLLECT_CODE'
        params.deviceId = userAppStore().lenovoToken ? '' : systemAppStore().appInfo.uuid

        console.log('请求xz_lysdk_pay参数：', JSON.stringify(params))
        // pay结果在 dealPayRes 中处理
        await invokeAsyncAPi('xz_lysdk_pay', JSON.stringify(params), this.openPos)
      }).catch(() => {
        this.setCodeError()
      })
    },
    setCodeError () {
      this.error = '请刷新二维码'
      this.loading = false
    },
    makePayCode () {
      const payURL = this.product.payURL
      if (this.qrcode && payURL) {
        this.qrcode.makeCode(payURL)
        this.qrcode._el.title = ''
        this.setTime(this.product.orderid)
      }
    },
    clearOrder () {
      // eslint-disable-next-line vue/no-mutating-props
      this.product.payURL = null
      // eslint-disable-next-line vue/no-mutating-props
      this.product.orderid = null
      // eslint-disable-next-line vue/no-mutating-props
      this.product.sign = null
      // eslint-disable-next-line vue/no-mutating-props
      this.product.otherParamsStr = null
    },
    async emitOrderStatus (status: any) {
      this.clearOrder()
      this.$emit('onStatusChange', status)
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./index.scss";

.lx-qr-code {
  position: relative;
  border-radius: 6px;
  padding-top: 28px !important;
  background: var(--el-color-primary);

  .code-box {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }

  .qr-error {
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    row-gap: 10px;

    .svg-icon {
      position: relative;
      inset: inherit;
      margin: 0;
    }

    .text-error {
      position: relative;
      inset: inherit;
    }
  }

  &::before {
    content: '';
    position: absolute;
    background: #FFFFFF;
    top: 1.5px;
    left: 1px;
    border-radius: 5px;
    width: calc(100% - 2px);
    height: calc(100% - 2.5px);
  }

  &::after {
    content: '联想应用商店';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    background: var(--el-color-primary);
    width: 80%;
    height: 20px;
    font-size: 12px;
    color: #fafafa;
    line-height: 20px;
    border-radius: 0 0 6px 6px;
  }

  &.error {
    &::after {
      display: none;
    }
  }
}
</style>
